/*
 * consola.c
 *
 *  Created on: 10/12/2009
 *      Author: teledhil
 */

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "comandos.h"
#include "consola.h"
#include "constantes.h"
#include "variablesGlobales.h"

int init_consola() {

	return 0;
}

int exit_consola() {

	return 0;
}

int output_user(char *nick, const char * format, ...) {

	va_list lista_argumentos;

	fprintf(stdout, "<%s> ", nick);
	va_start (lista_argumentos, format);
	vfprintf(stdout, format, lista_argumentos);
	va_end (lista_argumentos);
	fprintf(stdout, "\n");
	fflush(stdout);

	return 0;
}

int output_private(char *nick, const char * format, ...) {

	va_list lista_argumentos;

	fprintf(stdout, "*%s* ", nick);
	va_start (lista_argumentos, format);
	vfprintf(stdout, format, lista_argumentos);
	va_end (lista_argumentos);
	fprintf(stdout, "\n");
	fflush(stdout);

	return 0;
}

int output_program(const char * format, ...) {

	va_list lista_argumentos;

	fprintf(stdout, "*** ");
	va_start (lista_argumentos, format);
	vfprintf(stdout, format, lista_argumentos);
	va_end (lista_argumentos);
	fprintf(stdout, "\n");
	fflush(stdout);

	return 0;
}

int output_me(const char * format, ...) {

	va_list lista_argumentos;

	fprintf(stdout, "> ");
	va_start (lista_argumentos, format);
	vfprintf(stdout, format, lista_argumentos);
	va_end (lista_argumentos);
	fprintf(stdout, "\n");
	fflush(stdout);

	return 0;
}

int output_debug(const char * format, ...) {

	va_list lista_argumentos;

	if (debugMode) {
		fprintf(stdout, "DDD ");
		va_start (lista_argumentos, format);
		vfprintf(stdout, format, lista_argumentos);
		va_end (lista_argumentos);
		fprintf(stdout, "\n");
		fflush(stdout);
	}

	return 0;
}

int output_error(const char * format, ...) {

	va_list lista_argumentos;

	fprintf(stderr, "ERROR ");
	va_start (lista_argumentos, format);
	vfprintf(stderr, format, lista_argumentos);
	va_end (lista_argumentos);
	fprintf(stderr, "\n");
	fflush(stdout);

	return 0;
}

int output_perror(const char * format, ...) {

	va_list lista_argumentos;

	fprintf(stderr, "ERROR ");
	va_start (lista_argumentos, format);
	vfprintf(stderr, format, lista_argumentos);
	fprintf(stderr, ": ");
	perror("");
	va_end (lista_argumentos);
	fprintf(stderr, "\n");
	fflush(stdout);

	return 0;
}

int consola_leer_linea(char *linea, FILE *stream) {
	/*Devuelve: numero de caracteres leidos*/

	char *fin_linea;

	/*Obtiene una linea de stream*/
	if (fgets(linea, BUFFER, stream)) {
		/*Busca caracteres fin de linea y los sustituye por nulls*/
		fin_linea = strchr(linea, '\n');
		while (fin_linea) {
			*fin_linea = '\0';
			fin_linea = strchr(linea, '\n');
		}
	}

	//output_debug("leer_linea Linea: |%s|%d", linea, (int) strlen(linea));

	return (int) strlen(linea);
}

int consola_sacar_argumentos(char *linea, char **argv[]) {
	/*Devuelve: numero de argumentos leidos*/

	int num_argumentos = 0;
	/*char argumento[MAX_LONG_LINEA]="";
	 int offset=0;*/
	char *argumento;
	static char espacios[] = " \f\n\r\t\v";
	char *destino;
	char *ptOrigen, *ptDestino;
	char c, d = '\0';
	int i = 0;
	char **argumentos;

	/*fprintf(stderr,"@Debug sacar_argumentos Linea: |%s|%d\n",linea,
	 (int)strlen(linea));*/
	/*while ((sscanf(linea+offset, "%s", argumento))>0) {
	 fprintf(stderr,"@Debug sacar_argumentos Argumento: |%s|%d\n",
	 argumento,(int)strlen(argumento));

	 offset+=(int)strlen(argumento)+1;

	 //Vacia leido
	 memset(argumento,'\0',strlen(argumento));
	 num_argumentos++;
	 }*/

	destino = (char *) malloc((strlen(linea) + 1) * sizeof(char));
	if (destino == NULL) {
		fprintf(stderr, "Error en malloc destino\n");
		return -1;
	}

	//Copia los argumentos en un nuevo vector
	for (num_argumentos = 1, ptOrigen = linea, ptDestino = destino; (c
			= *ptOrigen); ptOrigen++, ptDestino++) {

		if (strchr(espacios, c)) {
			if (d != '\0') {
				num_argumentos++;
			}
			c = '\0';
		}
		d = c;
		*ptDestino = c;
	}
	*ptDestino = '\0';

	argumentos = (char **) malloc((num_argumentos + 1) * sizeof(char *));
	if (argumentos == NULL) {
		fprintf(stderr, "Error en malloc argumentos\n");
		return -1;
	}

	for (i = 0, ptOrigen = destino; ptOrigen < ptDestino; ptOrigen += (strlen(
			ptOrigen) + 1)) {

		if (*ptOrigen == '\0') {
			continue;
		}
		argumento = (char *) malloc((strlen(ptOrigen) + 1) * sizeof(char));
		strcpy(argumento, ptOrigen);
		argumentos[i] = argumento;
		i++;
		/*fprintf(stderr,"@Debug sacar_argumentos Argumento: |%s|%d\n",
		 argumento,(int)strlen(argumento));*/
	}
	argumentos[i] = NULL;

	/*i=0;
	 while(argumentos[i]!=NULL) {
	 fprintf(stderr,"@Debug sacar_argumentos Argumento (%d): |%s|\n",i+1,
	 argumentos[i]);
	 i++;
	 }*/

	/*Libera el vector destino*/
	free(destino);

	*argv = argumentos;

	return num_argumentos - 1;

}

int evaluar_linea(char *linea) {

	static char espacios[] = " \f\n\r\t\v";
	char *palabra, *ptCaracter, *ptr = NULL;
	bool seguir = true;
	char argumento1[BUFFER], argumento2[BUFFER];
	int numero, leidos = 0;

	/*Comprueba si la primera palabra es un comando*/
	if (COMMAND_CHARACTER == (*linea)) {

		/*obtiene la primera palabra de la linea*/
		for (ptCaracter = linea; ((*ptCaracter) != '\0') && seguir; ptCaracter++) {
			if (strchr(espacios, *ptCaracter)) {
				seguir = false;
				ptCaracter--;
			} else {
				/*output_debug("evaluarLinea. c=%c", *ptCaracter);*/
			}
		}
		palabra = (char *) calloc(1, (ptCaracter - linea + 1) * sizeof(char));
		strncat(palabra, linea, ptCaracter - linea);
		/*output_debug("evaluarLinea. palabra=%s", palabra);*/

		//Evalua la primera palabra
		if (strcmp(palabra, COMANDO_HELP) == 0) {
			help();

		} else if (strcmp(palabra, COMANDO_CONNECT) == 0) {
			/*Extrae servidor y puerto*/
			if ((leidos = sscanf(ptCaracter, "%s %s", argumento1, argumento2))
					!= 1) {
				if (leidos < 1) {
					output_program("The /connect command needs a host:port");
				} else if (leidos > 1) {
					output_program(
							"The /connect command only needs a host:port");
				}
				free(palabra);
				return -1;
			}
			ptCaracter = strchr(argumento1, ':');
			if (ptCaracter) {
				*ptCaracter = '\0';
				if ((numero = atoi(ptCaracter + 1)) == 0) {
					output_program("The /connect command also needs a port");
					output_debug("Puerto %d incorrecto", numero);
					free(palabra);
					return -1;
				}
			} else {
				output_program("The /connect command also needs a port");
				free(palabra);
				return -1;
			}
			/*Realiza la conexion*/
			connect(argumento1, numero);

		} else if (strcmp(palabra, COMANDO_AUTH) == 0) {
			if (sscanf(ptCaracter, "%s", argumento1) < 1) {
				output_error("Uso: /auth <nick>");
				free(palabra);
				return -1;
			}
			auth(argumento1);

		} else if (strcmp(palabra, COMANDO_LIST) == 0) {
			list();

		} else if (strcmp(palabra, COMANDO_JOIN) == 0) {
			if (sscanf(ptCaracter, "%s", argumento1) < 1) {
				output_error("Uso: /join <channel>");
				free(palabra);
				return -1;
			}
			join(argumento1);

		} else if (strcmp(palabra, COMANDO_LEAVE) == 0) {
			leave();

		} else if (strcmp(palabra, COMANDO_PART) == 0) {
			if (sscanf(ptCaracter, "%s", argumento1) < 1) {
				output_error("Uso: /part <channel>");
				free(palabra);
				return -1;
			}
			part(argumento1);

		} else if (strcmp(palabra, COMANDO_PING) == 0) {
			ping(NULL, NULL);

		} else if (strcmp(palabra, COMANDO_PONG) == 0) {
			pong(NULL, NULL);

		} else if (strcmp(palabra, COMANDO_WHO) == 0) {
			who();

		} else if (strcmp(palabra, COMANDO_MSG) == 0) {
			ptr = strtok(ptCaracter, " ");
			if (ptr) {
				strcpy(argumento1, ptr);
				ptr = strtok(NULL, " ");
				if (ptr) {
					msg_private(argumento1, ptr);
				}
			}

		} else if (strcmp(palabra, COMANDO_DISCONNECT) == 0) {
			disconnect();

		} else if (strcmp(palabra, COMANDO_QUIT) == 0) {
			quit();

		} else if (strcmp(palabra, COMANDO_NOP) == 0) {
			nop(ptCaracter);

		} else if (strcmp(palabra, COMANDO_SLEEP) == 0) {
			if (sscanf(ptCaracter, "%d", &numero) < 1) {
				output_error("Uso: /sleep <secs>");
				free(palabra);
				return -1;
			}
			sleep_ircc(numero);

		} else if (strcmp(palabra, COMANDO_OFFER) == 0) {
			if (sscanf(ptCaracter, "%s %s", argumento1, argumento2) < 2) {
				output_error("Uso: /offer <filename> <nick>");
				free(palabra);
				return -1;
			}
			offer(argumento1, argumento2);

		} else if (strcmp(palabra, COMANDO_DOWNLOAD) == 0) {
			if (sscanf(ptCaracter, "%s %s", argumento1, argumento2) < 2) {
				output_error("Uso: /download <filename> <server:port>");
				free(palabra);
				return -1;
			}
			ptCaracter = strchr(argumento2, ':');
			if (ptCaracter) {
				*ptCaracter = '\0';
				if ((numero = atoi(ptCaracter + 1)) == 0) {
					output_error("Puerto %d incorrecto", numero);
					free(palabra);
					return -1;
				}
			} else {
				output_error("Uso: /download <filename> <server:port>");
				free(palabra);
				return -1;
			}
			download(argumento1, argumento2, numero);

		} else {
			output_program("Comando %s desconocido", palabra);
		}

		/*Libera palabra*/
		free(palabra);

	} else {
		msg_all(linea);
	}

	return 0;
}

int bucle_consola() {

	char leido[BIG_BUFFER] = "";

	fflush(stdout);
	while (!state_powerOff) {
		if (consola_leer_linea(leido, stdin) > 0) {
			evaluar_linea(leido);
			/*Vacia leido*/
			memset(leido, '\0', strlen(leido));
		}
		fflush(stdout);
	}
	output_debug("Fin lectura comandos. IRCC se cierra\n");
	exit_consola();

	return 0;

}
